package SGEngine

import (
	//"fmt"
	"github.com/gl"
)

///动画的一帧
type AnimFrame struct {
	Size       Vec3
	TexCoordID gl.Buffer //纹理坐标
}

//一套动画
type Animation struct {
	Tex    *ACTexture //纹理
	Frames []*AnimFrame
}

const (
	ANIMTYPE_ONCE = 0
	ANIMTYPE_LOOP = 1
)

type AnimSprite struct {
	Node
	Animations map[string]*Animation
	VBufferID  gl.Buffer
	mProgram   *Program
	MColor     Color4

	CurAnimation *Animation
	CurFrame     int

	AnmType int

	anmupdater *Updater
	IsPlay     bool

	AnimEndCallFunc func()
}

func NewAnimSprite() *AnimSprite {
	RAnimSprite := new(AnimSprite)
	RAnimSprite.Node = DefaultNode()
	RAnimSprite.NodeRender = RAnimSprite
	RAnimSprite.mProgram = ACProgramMgr.GetProgram(PROGRAM_IMG)
	RAnimSprite.VBufferID = ACBufferMgr.GetVertexBuffer(BUFFER_Quad)
	RAnimSprite.MColor = NewColor4(1, 1, 1, 1)
	RAnimSprite.mProgram.ProgramObject.GetUniformLocation("inColor").Uniform4f(1, 1, 1, 1)
	uniformTexture := RAnimSprite.mProgram.ProgramObject.GetUniformLocation("s_texture")
	uniformTexture.Uniform1i(0)
	RAnimSprite.Animations = make(map[string]*Animation)
	RAnimSprite.IsPlay = false
	return RAnimSprite
}

func (a *AnimSprite) AddAnimSprite(name string, anim *Animation) {
	a.Animations[name] = anim
}

func (a *AnimSprite) Play(name string, uptime float64, AnimType int) {
	Anim, ishave := a.Animations[name]
	if !ishave {
		return
	}
	if a.IsPlay == false || a.anmupdater == nil {
		a.anmupdater = ACTimeUpdate.AddUpdater(AnimationUpdate, a, uptime)
	}
	a.anmupdater.updatetime = uptime
	a.IsPlay = true
	a.CurAnimation = Anim
	s := a.Size()
	*s = Anim.Frames[0].Size
	a.CurFrame = 0
	a.AnmType = AnimType
	a.AnimEndCallFunc = nil
}

func (a *AnimSprite) Stop() {
	a.IsPlay = false
	if a.anmupdater != nil {
		a.anmupdater.Del()
	}
}

func AnimationUpdate(dt float64, this interface{}) {
	Player := this.(*AnimSprite)
	Player.CurFrame++
	if Player.CurFrame > len(Player.CurAnimation.Frames)-1 {
		if Player.AnmType == ANIMTYPE_LOOP {
			Player.CurFrame = 0
		} else if Player.AnmType == ANIMTYPE_ONCE {
			Player.CurFrame = len(Player.CurAnimation.Frames) - 1
			//Player.IsPlay = false
			Player.anmupdater.Del()
			Player.anmupdater = nil
		}
		if Player.AnimEndCallFunc != nil {
			Player.AnimEndCallFunc()
		}
	}
}

func (a *AnimSprite) Render() {
	if a.IsPlay == false {

		return
	}
	gl.Enable(gl.ALPHA_TEST)
	gl.AlphaFunc(gl.GREATER, 0)

	a.CurAnimation.Tex.TexID.Bind(gl.TEXTURE_2D)
	a.mProgram.ProgramObject.Use()
	a.mProgram.ProgramObject.GetUniformLocation("inColor").Uniform4f(a.MColor.R, a.MColor.G, a.MColor.B, a.MColor.A)
	a.VBufferID.Bind(gl.ARRAY_BUFFER)
	a.mProgram.ProgramObject.GetAttribLocation("vPosition").AttribPointer(3, gl.FLOAT, false, 0, nil)
	a.mProgram.ProgramObject.GetAttribLocation("vPosition").EnableArray()
	a.CurAnimation.Frames[a.CurFrame].TexCoordID.Bind(gl.ARRAY_BUFFER)
	a.mProgram.ProgramObject.GetAttribLocation("a_texCoord").AttribPointer(2, gl.FLOAT, false, 0, nil)
	a.mProgram.ProgramObject.GetAttribLocation("a_texCoord").EnableArray()
	gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
	gl.Disable(gl.ALPHA_TEST)
}

func CreareAnimation_XTiled(imagename string, spriteWidth, spriteHeight, spriteNum int) *Animation {
	tex := ACTextureMgr.LoadTexture(imagename)
	RAnim := new(Animation)
	Frames := make([]*AnimFrame, spriteNum)
	RAnim.Tex = tex
	imgWidth := tex.Img.Bounds().Dx()
	SizeOneX := 1.0 / float32(imgWidth)
	SizeOneY := 1.0 / float32(tex.Img.Bounds().Dy())
	for i := 0; i < spriteNum; i++ {
		TexCoord := gl.GenBuffer()
		TexCoord.Bind(gl.ARRAY_BUFFER)
		TexCoordData := make([]float32, 8)
		//T1
		TexCoordData[0] = float32(i) * float32(spriteWidth) * SizeOneX
		TexCoordData[1] = 0
		//T2
		TexCoordData[2] = float32(i+1) * float32(spriteWidth) * SizeOneX
		TexCoordData[3] = 0
		//T3
		TexCoordData[4] = float32(i) * float32(spriteWidth) * SizeOneX
		TexCoordData[5] = float32(spriteHeight) * SizeOneY
		//T4
		TexCoordData[6] = float32(i+1) * float32(spriteWidth) * SizeOneX
		TexCoordData[7] = float32(spriteHeight) * SizeOneY

		gl.BufferData(gl.ARRAY_BUFFER, 8*4, TexCoordData, gl.STATIC_DRAW)
		Frame := new(AnimFrame)
		Frame.Size = Vec3{float64(spriteWidth), float64(spriteHeight), 1}
		Frame.TexCoordID = TexCoord
		Frames[i] = Frame
	}
	RAnim.Frames = Frames
	return RAnim
}
